using System;
using Velocity4Net.Runtime;
using Velocity4Net.Runtime.Logging;
using System.Reflection;
using System.Text;
using Velocity4Net.Runtime.Logging;

namespace Velocity4Net.Util.Introspection
{
    /**
     * This basic function of this class is to return a Method
     * object for a particular class given the name of a method
     * and the parameters to the method in the form of an Object[]
     *
     * The first time the Introspector sees a
     * class it creates a class method map for the
     * class in question. Basically the class method map
     * is a Hastable where Method objects are keyed by a
     * concatenation of the method name and the names of
     * classes that make up the parameters.
     *
     * For example, a method with the following signature:
     *
     * public void method(String a, StringBuffer b)
     *
     * would be mapped by the key:
     *
     * "method" + "java.lang.String" + "java.lang.StringBuffer"
     *
     * This mapping is performed for all the methods in a class
     * and stored for
     * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
     * @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
     * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
     * @author <a href="mailto:paulo.gaspar@krankikom.de">Paulo Gaspar</a>
     * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
     * @version $Id: Introspector.java 687177 2008-08-19 22:00:32Z nbubna $
     */
    public class Introspector : IntrospectorBase
    {
        /**
         * @param log A Log object to use for the introspector.
         * @since 1.5
         */
        public Introspector(Log log)
            : base(log)
        {
        }

        /**
         * Gets the method defined by <code>name</code> and
         * <code>params</code> for the Class <code>c</code>.
         *
         * @param c Class in which the method search is taking place
         * @param name Name of the method being searched for
         * @param params An array of Objects (not Classes) that describe the
         *               the parameters
         *
         * @return The desired Method object.
         * @throws IllegalArgumentException When the parameters passed in can not be used for introspection.
         */
        public MethodInfo getMethod(Type c, String name, Object[] _params)
        {
            try
            {
                return base.getMethod(c, name, _params);
            }
            catch (AmbiguousException ae)
            {
                /*
                 *  whoops.  Ambiguous.  Make a nice log message and return null...
                 */

                StringBuilder msg = new StringBuilder("Introspection Error : Ambiguous method invocation ")
                        .Append(name)
                        .Append("(");

                for (int i = 0; i < _params.Length; i++)
                {
                    if (i > 0)
                    {
                        msg.Append(", ");
                    }

                    if (_params[i] == null)
                    {
                        msg.Append("null");
                    }
                    else
                    {
                        msg.Append(_params[i].GetType().Name);
                    }
                }

                msg.Append(") for class ")
                        .Append(c);

                log.debug(msg.ToString());
            }

            return null;
        }

    }
}
